<?php
declare (strict_types=1);

namespace app\middleware;

use app\common\lib\Redis;
use app\common\model\PatientInfo;
use catchAdmin\permissions\model\Users;
use catcher\Code;
use catcher\exceptions\CatchException;
use catcher\exceptions\FailedException;
use thans\jwt\exception\JWTException;
use thans\jwt\exception\TokenInvalidException;
use thans\jwt\facade\JWTAuth;

class DoctorCheck
{
    /**
     * 处理请求
     *
     * @param \think\Request $request
     * @param \Closure $next
     * @return Response
     */
    public function handle($request, \Closure $next)
    {

        if ($request->method() === "OPTIONS") {
            return $next($request);
        }
        if (!$request->header("authorization")) {
            throw new FailedException("token无效", Code::LOST_LOGIN);
        }
        $sign = $request->header("sign");

        $requestId = $request->header("requestId");
        //判断requestId是否已经存在于redis记录中
        if (empty($requestId) || Redis::getInstance()->redis->keys("doctor:" . $requestId)) {
            # throw new FailedException("非法请求r");
        }
        try {
            # 解析token
            $token = $request->header("authorization");
            $tokenArr = explode(" ", $request->header("authorization"));
            $token = $tokenArr[1] ?? "";
            $jwtInfo = \thans\jwt\facade\JWTAuth::getPayload();

            $userId = (string)$jwtInfo["admin_id"];
            $this->checkToken($userId, $token);
            //判断requestId是否正确
            $genRequestId = hash("sha256", $userId . "ZHYX" . $sign);
            if ($genRequestId !== $requestId) {
                #throw new FailedException("非法请求r" . $genRequestId);
            }
            Redis::getInstance()->redis->setex("doctor:" . $requestId, 300, "OK");

            if ((string)$jwtInfo["platform"] === "1") {

                $userInfo = (new Users())->where("id", "=", $userId)->find();
            } else {
                $userInfo = (new PatientInfo())->where("id", "=", $userId)->find();
            }

            if (empty($userInfo)) {
                throw new FailedException("用户不存在", Code::LOGIN_FAILED);
            }
            $userInfo["platform"] = (string)$jwtInfo["platform"];
            $request->userInfo = $userInfo->toArray();


            return $next($request);

        } catch (TokenInvalidException $exception) {
            throw new FailedException("jwt解析失败", Code::VALIDATE_FAILED);

        } catch (JWTException $exception) {
            throw new FailedException($exception->getMessage());
        }

    }

    private function checkToken(string $userId, string $token): void
    {
        $userKey = hash("sha256", $userId . "_" . $_SERVER["REMOTE_ADDR"] . '_' . ($_SERVER["HTTP_USER_AGENT"] ?? ''));
        if (!Redis::getInstance()->redis->keys($userKey)) {
            #throw new FailedException("登录过期", Code::LOGIN_EXPIRED);
        } else {
            $redisToken = Redis::getInstance()->redis->get($userKey);
            if ($redisToken !== $token) {
                throw new FailedException("非法登录", Code::USER_FORBIDDEN);
            }
        }
        //判断用户传过来的token是否是用户自己
        $redisToken = Redis::getInstance()->redis->get("jwt:user:" . $userId) ?? "";
        if ($redisToken !== $token) {
            //throw new FailedException("非法登录111", Code::USER_FORBIDDEN);
        }

        //判断token时间
        $ttl = Redis::getInstance()->redis->ttl($userKey);
        if ($ttl < 1800) {
            Redis::getInstance()->redis->expireat($userKey, time() + $ttl + 1800);
        }


    }


}
